package thinking.in.spring.boot.example;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author : wenchao.long
 * @date : Created in 2024-12-31 下午 10:55 周二
 * @description :
 */
@SpringBootApplication()
public class TransactionalServiceAnnotationReflectionBootstrap {

	public static void main(String[] args) {
		// Class实现了AnnotatedElement接口
		AnnotatedElement annotatedElement =
				TransactionalServiceAnnotationReflectionBootstrap.class;
		// 从AnnotatedElement获取Transactional
		SpringBootApplication transactional = annotatedElement.getAnnotation(SpringBootApplication.class);
		// 获取transactional的所有元注解
		Set<Annotation> allMetaAnnotations = getAllMetaAnnotations(transactional);
		allMetaAnnotations.forEach(TransactionalServiceAnnotationReflectionBootstrap::printAnnotations);
	}

	private static Set<Annotation> getAllMetaAnnotations(Annotation Annotation) {
		Annotation[] metaAnnotations = Annotation.annotationType().getAnnotations();

		// 没有找到，返回空集合
		if (ObjectUtils.isEmpty(metaAnnotations)) {
			return Collections.emptySet();
		}

		Set<Annotation> annotationSet = Stream.of(metaAnnotations)
				.filter(metaAnnotation -> !Target.class.getPackage().equals(metaAnnotation.annotationType().getPackage()))
				.collect(Collectors.toSet());

		HashSet<Annotation> metaAnnotationSet = annotationSet.stream().map(TransactionalServiceAnnotationReflectionBootstrap::getAllMetaAnnotations)
				.collect(HashSet::new, HashSet::addAll, HashSet::addAll);

		annotationSet.addAll(metaAnnotationSet);

		return annotationSet;
	}

	private static void printAnnotations(Annotation annotation) {
		Class<? extends Annotation> annotationType = annotation.annotationType();
		// 完全Java反射实现(ReflectionUtils 为Spring反射工具类)
		ReflectionUtils.doWithMethods(annotationType, method -> System.out.printf("@%s.%s() = %s\n",
						annotationType.getSimpleName(), method.getName(), ReflectionUtils.invokeMethod(method, annotation)),
				//method -> method.getParameterCount() == 0);// 选择无参数方法
				// 选择非Annotation方法
				method -> !method.getDeclaringClass().equals(Annotation.class));
	}
}
